﻿/****************************************************************
*   作者：Morain
*   创建时间：2018/2/25 18:03:42
*   描述说明：
*****************************************************************/
using System;
using System.Collections.Generic;
using System.Text;

namespace Model
{
  [ObjectSystem]
  public class MessageDispatcherComponentSystem : ObjectSystem<MessageDispatcherComponent>, IAwake
  {
    public void Awake()
    {
      Get().Awake();
    }
  }

  public class MessageDispatcherComponent : Component
  {
    private Dictionary<Type, List<IMHandler>> handlers;


    public void Awake()
    {
      this.Load();
    }

    public void Load()
    {
      AppType appType = Game.Scene.GetComponent<StartConfigComponent>().StartConfig.AppType;

      this.handlers = new Dictionary<Type, List<IMHandler>>();

      Type[] types = DllHelper.GetAll();

      foreach (Type type in types)
      {
        object[] attrs = type.GetCustomAttributes(typeof(MessageHandlerAttribute), false);
        if (attrs.Length == 0) continue;

        MessageHandlerAttribute messageHandlerAttribute = (MessageHandlerAttribute)attrs[0];

        if (!appType.HasFlag(messageHandlerAttribute.Type))
        {
          continue;
        }

        object obj = Activator.CreateInstance(type);
        IMHandler mHandler = obj as IMHandler;
        if (mHandler == null)
          throw new Exception($"message handler not inherit AMEvent or AMRpcEvent abstract class: {obj.GetType().FullName}");

        Type messateType = mHandler.GetMessageType();
        if (!this.handlers.TryGetValue(messateType, out List<IMHandler> list))
        {
          list = new List<IMHandler>();
          this.handlers.Add(messateType, list);
        }
        list.Add(mHandler);
      }
    }

    public void Handle(Session session, uint rpcId, IMessage message)
    {
      if (!this.handlers.TryGetValue(message.GetType(), out List<IMHandler> actions))
      {
        Log.Error($"消息 {message.GetType().FullName} 没有处理");
        return;
      }

      foreach (IMHandler action in actions)
      {
        try
        {
          action.Handle(session, rpcId, message);
        }
        catch (Exception e)
        {
          Log.Error(e.ToString());
        }
      }
    }

    public override void Dispose()
    {
      if (this.Id == 0)
        return;
      base.Dispose();
    }
  }
}
